#include "RoadForm.h"
#include "NavigationManager.h"
#include "OpennavUtils.h"

using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::Base::Collection;
using namespace Osp::Ui;
using namespace Osp::Ui::Controls;
using namespace Osp::Graphics;
using namespace Osp::Io;
using namespace Osp::Text;

RoadForm::RoadForm()
	: __pSearchService(null), __pMap(null), __pCurrentResult(null), __pLock(null), __currentCityId(0) { }

result RoadForm::Construct(OpennavSearchServiceProvider* searchService, OpennavMap* map) {
	Form::Construct(L"IDF_SELECT_ROAD");
	__pSearchService = searchService;
	__pMap = map;
	return E_SUCCESS;
}

result RoadForm::OnInitializing() {
	result r = E_SUCCESS;
	__pScrollPanel = static_cast<ScrollPanel *>(GetControl(L"IDC_SCROLLPANEL1", false));
	__pListRoad = static_cast<SlidableList *>(GetControl(L"IDPC_LIST_ROAD", true));
	if (__pListRoad != null) {
		__pListRoad->AddSlidableListEventListener(*this);
		__pListRoad->AddCustomItemEventListener(*this);
	}
	__pSearchRoad = static_cast<EditField *>(GetControl(L"IDPC_SEARCH_ROAD", true));
	if (__pSearchRoad != null) {
		__pSearchRoad->AddTextEventListener(*this);
		__pSearchRoad->AddActionEventListener(*this);
		__pSearchRoad->SetOverlayKeypadCommandButton(COMMAND_BUTTON_POSITION_RIGHT, L"Close", ID_BUTTON_EDITFIELD_CLOSE);
	}
	__pCustomListItemFormat = new CustomListItemFormat();
	__pCustomListItemFormat->Construct();
	__pCustomListItemFormat->AddElement(ROAD_NAME_ID, Osp::Graphics::Rectangle(10, 10, 460, 55), 40);
	__pCustomListItemFormat->AddElement(WHERE_NAME_ID, Osp::Graphics::Rectangle(10, 65, 460, 30), 25);
	SetSoftkeyActionId(SOFTKEY_1, ID_SOFTKEY_BACK);
	AddSoftkeyActionListener(SOFTKEY_1, *this);
	__pLock = new Mutex();
	__pLock->Create();
	return r;
}

result RoadForm::OnTerminating() {
	result r = E_SUCCESS;
	delete __pCustomListItemFormat;
	delete __pLock;
	return r;
}

void RoadForm::OnActionPerformed(const Osp::Ui::Control& source, int actionId) {
	switch (actionId) {
		case ID_BUTTON_EDITFIELD_CLOSE:
			{
				__pScrollPanel->CloseOverlayWindow();
				__pSearchRoad->Draw();
				__pSearchRoad->Show();
			}
			break;
		case ID_SOFTKEY_BACK:
			{
				Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
				NavigationManager *pNavManager = static_cast<NavigationManager *>(pFrame->GetControl(NavigationManager::FORM_MANAGER_NAME));
				if (pNavManager != null) {
					pNavManager->SendUserEvent(NavigationManager::REQUEST_ID_CITY_FORM, null);
				}
			}
			break;
		default:
			break;
	}
}

void RoadForm::OnTextValueChanged(const Osp::Ui::Control& source) {
	PerformSearch();
}

void RoadForm::OnLoadToTopRequested(const Osp::Ui::Control &source, int index, int numItems)
{
	if (__pListRoad != null) {
		__pLock->Acquire();
		for(int i = index; i > index - numItems; i--) {
			opennav::Road road;
			__pCurrentResult->GetResult(i, road);
			String roadName;
			OpennavUtils::Convert(road.labels.at(0), roadName);
			CustomListItem* pItem = new CustomListItem();
			pItem->Construct(100);
			pItem->SetItemFormat(*__pCustomListItemFormat);
			pItem->SetElement(ROAD_NAME_ID, roadName);
			pItem->SetElement(WHERE_NAME_ID, GetWhereCity(road));
			__pListRoad->LoadItemToTop(*pItem, road.road_id);
		}
		__pLock->Release();
	}
}

void RoadForm::OnLoadToBottomRequested (const Osp::Ui::Control &source, int index, int numItems)
{
	if (__pListRoad != null) {
		__pLock->Acquire();
		for(int i = index; i < index + numItems; i++) {
			opennav::Road road;
			__pCurrentResult->GetResult(i, road);
			String roadName;
			OpennavUtils::Convert(road.labels.at(0), roadName);
			CustomListItem* pItem = new CustomListItem();
			pItem->Construct(100);
			pItem->SetItemFormat(*__pCustomListItemFormat);
			pItem->SetElement(ROAD_NAME_ID, roadName);
			pItem->SetElement(WHERE_NAME_ID, GetWhereCity(road));
			__pListRoad->LoadItemToBottom(*pItem, road.road_id);
		}
		__pLock->Release();
	}
}

void RoadForm::OnItemStateChanged(const Osp::Ui::Control &source, int index, int itemId, Osp::Ui::ItemStatus status) {
	Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
	NavigationManager *pNavManager = static_cast<NavigationManager *>(pFrame->GetControl(NavigationManager::FORM_MANAGER_NAME));
	if (pNavManager != null) {
		ArrayList* args = new ArrayList();
		args->Construct();
		args->Add(*(new Integer(itemId)));
		//pNavManager->SendUserEvent(NavigationManager::REQUEST_ID_ADDRESS_STREET_BY_CITY, args);
	}
}

void RoadForm::OnUserEventReceivedN(RequestId requestId, IList* pArgs) {
	switch(requestId)
	{
		case REQUEST_ID_SET_CITY:
			{
				__currentCityId = ((Integer*)pArgs->GetAt(0))->ToInt();
				__pSearchRoad->SetText(Osp::Base::String(""));
				PerformSearch();
			}
			break;
		default:
			break;
	}
}

void RoadForm::OnGeocodingRequestResultReceived(IOpennavSearchResult* result) {
	AppLogDebug("search road request callback");
	if (result->GetRequestType() == SEARCH_ROAD) {
		if (__pCurrentResult != null) {
			delete __pCurrentResult;
		}
		__pCurrentResult = (OpennavSearchRoadResult*)result;
		__pListRoad->RemoveAllItems();
		__pListRoad->SetItemCountAndHeight(__pCurrentResult->GetCount(), __pCurrentResult->GetCount() * 100);
		__pListRoad->Draw();
		__pListRoad->Show();
		RequestRedraw(true);
	}
}

void RoadForm::PerformSearch() {
	String text = __pSearchRoad->GetText();
	__pLock->Acquire();
	__pListRoad->RemoveAllItems();
	if (__pCurrentResult != null) {
		delete __pCurrentResult;
		__pCurrentResult = null;
	}
	__pListRoad->SetItemCountAndHeight(0, 0);
	__pLock->Release();
	OpennavSearchRoadRequest request = OpennavSearchRoadRequest(text, __currentCityId);
	__pSearchService->Search(request, *this);
	RequestRedraw(true);
}

Osp::Base::String RoadForm::GetWhereCity(opennav::Road& road) {
	Osp::Base::String result;
	bool first = true;
	City currentCity;
	__pMap->GetCity(road.city_id, currentCity);
	while (true) {
		if (!first) {
			result.Append(L", ");
		}
		first = false;
		Osp::Base::String cityName;
		OpennavUtils::Convert(currentCity.name, cityName);
		result.Append(cityName);
		if (currentCity.parent_city_id < 0)
			break;
		__pMap->GetCity(currentCity.parent_city_id, currentCity);
	}
	return result;
}

